# -*- coding: utf-8 -*-
"""
    sphinx.transforms.post_transforms.compat
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Post transforms for compatibility

    :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

import warnings

from docutils import nodes
from docutils.writers.docutils_xml import XMLTranslator

from sphinx.addnodes import math_block, displaymath
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.transforms import SphinxTransform
from sphinx.util import logging

if False:
    # For type annotation
    from typing import Any, Callable, Dict, Iterable, List, Tuple  # NOQA
    from docutils.parsers.rst.states import Inliner  # NOQA
    from docutils.writers.html4css1 import Writer  # NOQA
    from sphinx.application import Sphinx  # NOQA
    from sphinx.builders import Builder  # NOQA
    from sphinx.environment import BuildEnvironment  # NOQA

logger = logging.getLogger(__name__)


class MathNodeMigrator(SphinxTransform):
    """Migrate a math node to docutils'.

    For a long time, Sphinx uses an original node for math. Since 1.8,
    Sphinx starts to use a math node of docutils'.  This transform converts
    old and new nodes to keep compatibility.
    """
    default_priority = 999

    def apply(self):
        # type: () -> None
        for node in self.document.traverse(nodes.math):
            # case: old styled ``math`` node generated by old extensions
            if len(node) == 0:
                warnings.warn("math node for Sphinx was replaced by docutils'. "
                              "Please use ``docutils.nodes.math`` instead.",
                              RemovedInSphinx30Warning)
                equation = node['latex']
                node += nodes.Text(equation, equation)

        translator = self.app.builder.get_translator_class()
        if hasattr(translator, 'visit_displaymath') and translator != XMLTranslator:
            # case: old translators which does not support ``math_block`` node
            warnings.warn("Translator for %s does not support math_block node'. "
                          "Please update your extension." % translator,
                          RemovedInSphinx30Warning)
            for node in self.document.traverse(math_block):
                alt = displaymath(latex=node.astext(),
                                  number=node.get('number'),
                                  label=node.get('label'),
                                  nowrap=node.get('nowrap'),
                                  docname=node.get('docname'))
                node.replace(alt)
        elif getattr(self.app.builder, 'math_renderer_name', None) == 'unknown':
            # case: math extension provides old styled math renderer
            for node in self.document.traverse(nodes.math_block):
                node['latex'] = node.astext()

        # case: old styled ``displaymath`` node generated by old extensions
        for node in self.document.traverse(math_block):
            if len(node) == 0:
                warnings.warn("math node for Sphinx was replaced by docutils'. "
                              "Please use ``docutils.nodes.math_block`` instead.",
                              RemovedInSphinx30Warning)
                if isinstance(node, displaymath):
                    newnode = nodes.math_block('', node['latex'], **node.attributes)
                    node.replace_self(newnode)
                else:
                    latex = node['latex']
                    node += nodes.Text(latex, latex)


def setup(app):
    # type: (Sphinx) -> Dict[unicode, Any]
    app.add_post_transform(MathNodeMigrator)

    return {
        'version': 'builtin',
        'parallel_read_safe': True,
        'parallel_write_safe': True,
    }
